package com.fingard.dsp.bank.directbank.weixin01.domain.common;

import java.util.EnumMap;

/**
 * 【跨城冗灾】配置
 * @author liujinhui
 */
public class DomainConfig {

    // 双活情况下备用域名出现比率
    private int reserveDomainReferRate;
    // 定时器-上报结果分析执行频率，实现主备域名实时切换（毫秒）
    private int resultReportFrequency;
    // 上报数据最大限制
    private int resultDataMaxSize;
    // 主域名上报结果成功通过率
    private int reportPassingRate;
    // 定时器-探测主域名连通性执行频率，实现主备域名实时切换（毫秒）
    private int domainProbeFrequency;

    /********************************* 默认参数枚举配置开始 ****************************/
    /**
     * LOW:万分之一，DEFAULT:千分之一，HIGH:百分之一
     */
    public enum ReserveDomainReferRate {
        DEFAULT, LOW, HIGH
    }

    /**
     * LOW:10秒，DEFAULT:1分钟，HIGH:5分钟
     */
    public enum ResultReportFrequency {
        DEFAULT, LOW, HIGH
    }

    /**
     * LOW:50，DEFAULT:100，HIGH:200
     */
    public enum ResultDataMaxSize {
        DEFAULT, LOW, HIGH
    }

    /**
     * LOW:百分之80，DEFAULT:百分之85，HIGH:百分之90
     */
    public enum ReportPassingRate {
        DEFAULT, LOW, HIGH
    }

    /**
     * LOW:10秒，DEFAULT:1分钟，HIGH:5分钟
     */
    public enum DomainProbeFrequency {
        DEFAULT, LOW, HIGH
    }

    /********************************* 默认参数枚举配置结束 ****************************/

    /********************************* 枚举对应实际参数设置开始 ****************************/
    // 双活情况下备用域名出现比率
    private static final EnumMap<ReserveDomainReferRate, Integer> 
    reserveDomainReferRateMap = new EnumMap<ReserveDomainReferRate, Integer>(ReserveDomainReferRate.class);
    static {
        reserveDomainReferRateMap.put(ReserveDomainReferRate.DEFAULT, 10);
        reserveDomainReferRateMap.put(ReserveDomainReferRate.LOW, 1);
        reserveDomainReferRateMap.put(ReserveDomainReferRate.HIGH, 100);
    }
    // 定时器-上报结果分析执行频率，实现主备域名实时切换
    private static final EnumMap<ResultReportFrequency, Integer> 
    resultReportFrequencyMap = new EnumMap<ResultReportFrequency, Integer>(ResultReportFrequency.class);
    static {
        resultReportFrequencyMap.put(ResultReportFrequency.DEFAULT, 10 * 1000);
        resultReportFrequencyMap.put(ResultReportFrequency.LOW, 60 * 1000);
        resultReportFrequencyMap.put(ResultReportFrequency.HIGH, 5 * 60 * 1000);
    }
    // 上报数据最大限制
    private static final EnumMap<ResultDataMaxSize, Integer> 
    resultDataMaxSizeMap = new EnumMap<ResultDataMaxSize, Integer>(ResultDataMaxSize.class);
    static {
        resultDataMaxSizeMap.put(ResultDataMaxSize.DEFAULT, 50);
        resultDataMaxSizeMap.put(ResultDataMaxSize.LOW, 100);
        resultDataMaxSizeMap.put(ResultDataMaxSize.HIGH, 200);
    }
    // 主域名上报结果成功通过率
    private static final EnumMap<ReportPassingRate, Integer> 
    reportPassingRateMap = new EnumMap<ReportPassingRate, Integer>(ReportPassingRate.class);
    static {
        reportPassingRateMap.put(ReportPassingRate.DEFAULT, 80);
        reportPassingRateMap.put(ReportPassingRate.LOW, 85);
        reportPassingRateMap.put(ReportPassingRate.HIGH, 90);
    }
    // 定时器-探测主域名连通性执行频率，实现主备域名实时切换
    private static final EnumMap<DomainProbeFrequency, Integer> 
    domainProbeFrequencyMap = new EnumMap<DomainProbeFrequency, Integer>(DomainProbeFrequency.class);
    static {
        domainProbeFrequencyMap.put(DomainProbeFrequency.DEFAULT, 10 * 1000);
        domainProbeFrequencyMap.put(DomainProbeFrequency.LOW, 60 * 1000);
        domainProbeFrequencyMap.put(DomainProbeFrequency.HIGH, 5 * 60 * 1000);
    }

    /********************************* 枚举对应实际参数设置结束 ****************************/

    private DomainConfig() {

    }

    private DomainConfig(DomainConfig conf) {
        this.reserveDomainReferRate = conf.reserveDomainReferRate;
        this.resultReportFrequency = conf.resultReportFrequency;
        this.resultDataMaxSize = conf.resultDataMaxSize;
        this.reportPassingRate = conf.reportPassingRate;
        this.domainProbeFrequency = conf.domainProbeFrequency;
    }

    public int getReserveDomainReferRate() {
        return reserveDomainReferRate;
    }

    public int getResultReportFrequency() {
        return resultReportFrequency;
    }

    public int getResultDataMaxSize() {
        return resultDataMaxSize;
    }

    public int getReportPassingRate() {
        return reportPassingRate;
    }

    public int getDomainProbeFrequency() {
        return domainProbeFrequency;
    }

    /**
     * DomainConfig.Builder构建配置
     * @author liujinhui
     */
    public static class Builder {

        private DomainConfig conf;

        public Builder() {
            conf = new DomainConfig();
        }

        /**
         * 双活情况下备用域名出现比率：这个方法用来设置主备域名流量分配情况，
         * 例如value=2，表示0.02%的流量走备用域名，99.98%的流量走主域名， 用户可根据自身业务流量状况传递1-10000之间的数值。
         * @param value
         * @return
         */
        public Builder reserveDomainReferRate(int value) {
            if (value <= 0 || value > 10000) {
                throw new IllegalArgumentException("参数在1-10000之间【万分比】");
            }
            conf.reserveDomainReferRate = value;
            return this;
        }

        /**
         * 双活情况下备用域名出现比率：使用枚举:ReserveDomainReferRate,枚举值选择参考枚举解释。
         * @param valueE
         * @return
         */
        public Builder reserveDomainReferRate(ReserveDomainReferRate valueE) {
            return this.reserveDomainReferRate(reserveDomainReferRateMap.get(valueE));
        }

        /**
         * 定时器-上报结果分析执行频率，实现主备域名实时切换：这个方法用来设置定时器
         * 多久执行一次上报结果分析策略计算逻辑，例如value=10000，表示10秒执行一
         * 次，用户可根据自身业务状况传递大于等于10000的数值（单位毫秒）。
         * @param value
         * @return
         */
        public Builder resultReportFrequency(int value) {
            if (value < 10000) {
                throw new IllegalArgumentException("参数必须大于等于10000【毫秒】");
            }
            conf.resultReportFrequency = value;
            return this;
        }

        /**
         * 定时器-上报结果分析执行频率，实现主备域名实时切换：使用枚举: ResultReportFrequency,枚举值选择参考枚举解释。
         * @param valueE
         * @return
         */
        public Builder resultReportFrequency(ResultReportFrequency valueE) {
            return this.resultReportFrequency(resultReportFrequencyMap.get(valueE));
        }

        /**
         * 上报数据最大限制：这个方法用来设置请求结果上报数据存储器最大能保留的数据量，
         * 例如value=100，表示上报数据最多保留100条，当数据满足100条后再次上报会清
         * 除最早的数据使数据存储器不会超过100的限制，用户可根据自身业务状况传递大于50的数值。
         * @param value
         * @return
         */
        public Builder resultDataMaxSize(int value) {
            if (value < 50) {
                throw new IllegalArgumentException("参数必须大于50【上报结果保留条数】");
            }
            conf.resultDataMaxSize = value;
            return this;
        }

        /**
         * 上报数据最大限制：使用枚举: ResultDataMaxSize,枚举值选择参考枚举解释。
         * @param valueE
         * @return
         */
        public Builder resultDataMaxSize(ResultDataMaxSize valueE) {
            return this.resultDataMaxSize(resultDataMaxSizeMap.get(valueE));
        }

        /**
         * 主域名上报结果成功通过率：这个方法用来比较由请求结果上报数据计算出的主域名通过百分率和value值，
         * 当主域名通过百分率大于等于value值是会选择主域名，当主域名通过百分率小于value值是会选择备用名，
         * 例如value=90，表示主域名通过百分率只有在大于等于90%的情况下才会切换为主域名、小于会切换备用域
         * 名，用户可根据自身业务状况传递80-100的数值。
         * @param reportPassingRate
         * @return
         */
        public Builder reportPassingRate(int value) {
            if (value < 80 || value > 100) {
                throw new IllegalArgumentException("参数在80-100之间【上报结果成功通过率】");
            }
            conf.reportPassingRate = value;
            return this;
        }

        /**
         * 主域名上报结果成功通过率： ReportPassingRate,枚举值选择参考枚举解释。
         * @param valueE
         * @return
         */
        public Builder reportPassingRate(ReportPassingRate valueE) {
            return this.reportPassingRate(reportPassingRateMap.get(valueE));
        }

        /**
         * 定时器-探测主域名连通性执行频率，实现主备域名实时切换：这个方法用来设置定时器
         * 多久探测主域名连通性逻辑，例如value=10000，表示10秒执行一次，用户可根据自
         * 身业务状况传递大于等于10000的数值（单位毫秒）。
         * @param value
         * @return
         */
        public Builder domainProbeFrequency(int value) {
            if (value < 10000) {
                throw new IllegalArgumentException("参数必须大于等于10000【单位毫秒】");
            }
            conf.domainProbeFrequency = value;
            return this;
        }

        /**
         * 定时器-探测主域名连通性执行频率，实现主备域名实时切换：使用枚举: DomainProbeFrequency,枚举值选择参考枚举解释。
         * @param valueE
         * @return
         */
        public Builder domainProbeFrequency(DomainProbeFrequency valueE) {
            return this.domainProbeFrequency(domainProbeFrequencyMap.get(valueE));
        }

        public DomainConfig build() {
            // 双活情况下备用域名出现比率默认值设置
            if (conf.reserveDomainReferRate <= 0) {
                conf.reserveDomainReferRate = reserveDomainReferRateMap
                        .get(ReserveDomainReferRate.DEFAULT);
            }
            // 定时器-上报结果分析执行频率，实现主备域名实时切换默认值设置
            if (conf.resultReportFrequency <= 0) {
                conf.resultReportFrequency = resultReportFrequencyMap
                        .get(ResultReportFrequency.DEFAULT);
            }
            // 上报数据最大限制默认值设置
            if (conf.resultDataMaxSize <= 0) {
                conf.resultDataMaxSize = resultDataMaxSizeMap
                        .get(ResultDataMaxSize.DEFAULT);
            }
            // 主域名上报结果成功通过率默认值设置
            if (conf.reportPassingRate <= 0) {
                conf.reportPassingRate = reportPassingRateMap
                        .get(ReportPassingRate.DEFAULT);
            }
            // 定时器-探测主域名连通性执行频率，实现主备域名实时切换默认值设置
            if (conf.domainProbeFrequency <= 0) {
                conf.domainProbeFrequency = domainProbeFrequencyMap
                        .get(DomainProbeFrequency.DEFAULT);
            }
            return new DomainConfig(conf);
        }
    }
}
